﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.Ports;
using System.Windows.Forms;
using nStruct;
namespace nRS232
{
	public static class cRS232CMD
	{
		public const byte cmdDeviceOKQuery = 0x01;

		public const byte cmdStartStop = 0x10;
		public const byte cmdStartStopQuery = 0x1A;
		public const byte cmdStartStopQueryReturn = 0x1F;

		public const byte cmdStatusAllQuery = 0xAA;
		public const byte cmdStatusAllQueryReturn = 0xAF;

		public const byte cmdPsConfigSet = 0x50;
		public const byte cmdPsConfigSetQuery = 0x5A;
		public const byte cmdPsConfigSetQueryReturn = 0x5F;

		public const byte cmdTempConfigSet = 0x60;
		public const byte cmdTempConfigSetQuery = 0x6A;
		public const byte cmdTempConfigSetQueryReturn = 0x6F;

		public const byte cmdReceiveOKReturn = 0xFF;



		public const byte cmdENGMODE_Set = 0xC0;
		
	}

	public static class cRS232
	{
		public static int MaxCH = 3;
		public static int[] ReceiveFlag = new int[MaxCH];
		public static int MaxBuffer = 65536;
		public const int MaxB = 65536;
		public static byte[,] CMD_RxBuf = new byte[MaxCH, MaxB];
		public static byte[,] BUF = new byte[MaxCH, MaxB];
		public static int[] Head = new int[MaxCH];
		public static int[] Tail = new int[MaxCH];

		public static int SendCNT = 0;
		public static int RecCNT = 0;
		public static int[] CMD_RX_STATE = new int[MaxCH];
		public static int[] CMD_Checksum = new int[MaxCH];
		public static int[] CMD_RxDataCount = new int[MaxCH];
		public static int[] CMD_DataSize1 = new int[MaxCH];
		public static int[] CMD_DataSize = new int[MaxCH];
		public static int[] size = new int[MaxCH];
		public static int[] CMD = new int[MaxCH];
		public static byte[,] data = new byte[MaxCH, MaxB];

		const int CMD_STX = 0;
		const int CMD_CMD = 1;
		const int CMD_SIZE1 = 2;
		const int CMD_SIZE2 = 3;
		const int CMD_DATA = 4;
		const int CMD_CS = 5;

		//포트 인스턴스 생성

		public static SerialPort[] msc = new SerialPort[MaxCH];
		public static bool Status = false;

		public static void RS232_INIT(int inCH)
		{
			CMD_RX_STATE[inCH] = CMD_STX;
			Head[inCH] = 0;
			Tail[inCH] = 0;
			if (cRS232.msc[inCH].IsOpen) cRS232.msc[inCH].DiscardInBuffer();
		}

		public static bool CMD_GetData(int inCH, out byte CH)
		{
			bool ret = false;

			if (Tail[inCH] == Head[inCH])
			{
				ret = false;
				CH = 0;
			}
			else
			{
				CH = BUF[inCH, Tail[inCH]++];
				Tail[inCH] = Tail[inCH] % MaxBuffer;
				ret = true;
			}
			return ret;
		}

		public static bool CMD_MessageFromDevice(int inCH)
		{
			bool ret;
			byte ch = 0;
			ret = false;

			while (true)
			{
				if (CMD_GetData(inCH, out ch) == false) break;
				Application.DoEvents();
				switch (CMD_RX_STATE[inCH])
				{
					case CMD_STX:
						if (ch == 0x02) CMD_RX_STATE[inCH] = CMD_CMD;
						CMD_RxBuf[inCH, 0] = ch;
						CMD_Checksum[inCH] = 0;
						break;
					case CMD_CMD:
						CMD_RX_STATE[inCH] = CMD_SIZE1;
						CMD_RxBuf[inCH, 1] = ch;
						CMD_Checksum[inCH] = CMD_Checksum[inCH] + ch;
						CMD_Checksum[inCH] = CMD_Checksum[inCH] % 256;
						break;
					case CMD_SIZE1:
						CMD_RX_STATE[inCH] = CMD_SIZE2;
						CMD_RxBuf[inCH, 2] = ch;
						CMD_DataSize[inCH] = ((int)ch) * 256;
						CMD_Checksum[inCH] = CMD_Checksum[inCH] + ch;
						CMD_Checksum[inCH] = CMD_Checksum[inCH] % 256;
						break;
					case CMD_SIZE2:
						CMD_RxBuf[inCH, 3] = ch;
						CMD_DataSize[inCH] += (int)ch;
						CMD_RxDataCount[inCH] = 0;
						if (CMD_DataSize[inCH] == 0) CMD_RX_STATE[inCH] = CMD_CS;
						else CMD_RX_STATE[inCH] = CMD_DATA;

						CMD_Checksum[inCH] = CMD_Checksum[inCH] + ch;
						CMD_Checksum[inCH] = CMD_Checksum[inCH] % 256;
						break;
					case CMD_DATA:
						CMD_RxBuf[inCH, 4 + CMD_RxDataCount[inCH]] = ch;
						CMD_RxDataCount[inCH]++;
						CMD_Checksum[inCH] = CMD_Checksum[inCH] + ch;
						CMD_Checksum[inCH] = CMD_Checksum[inCH] % 256;
						if (CMD_RxDataCount[inCH] >= CMD_DataSize[inCH]) CMD_RX_STATE[inCH] = CMD_CS;
						break;
					case CMD_CS:
						CMD_RX_STATE[inCH] = CMD_STX;
						if (ch == (255 - CMD_Checksum[inCH]))
						{
							CMD_RxBuf[inCH, 5 + CMD_RxDataCount[inCH]] = (byte)ch;
							return true;
						}
						else
						{
							RS232_INIT(inCH);
							return false;
						}
				}
			}

			return ret;
		}

		public static string Set_RS232(Com_Conf_Struct inPort, int inCH, bool inKey)
		{

			msc[inCH] = new SerialPort(inPort.PortName[inCH], inPort.Speed[inCH], Parity.None, 8, StopBits.One);

			CMD_RX_STATE[inCH] = CMD_STX;
			Head[inCH] = 0;
			Tail[inCH] = 0;

			msc[inCH].Parity = 0;
			msc[inCH].DataBits = 8;
			msc[inCH].ReadTimeout = 500;
			msc[inCH].WriteTimeout = 500;
			msc[inCH].ReadBufferSize = 65536;
			if (inKey == true)
			{
				try
				{
					msc[inCH].Open();
					RS232_INIT(inCH);
				}
				catch
				{
				}
			}
			else
			{
				try
				{
					if (msc[inCH].IsOpen == true)
					{
						msc[inCH].Close();
						Status = false;
					}
				}
				catch
				{

				}
			}

			if (msc[inCH].IsOpen == true) return msc[inCH].PortName;
			else return "not found";
		}

		public static void RS232Command(int inCH, byte inCMD, int size, byte[] inBuf)
		{
			byte[] OutData = new byte[2048];
			int chksum = 0;
			int add = 0;
			OutData[add++] = 0x02;
			OutData[add++] = (byte)inCMD;
			OutData[add++] = (byte)(size / 256);	//size1
			OutData[add++] = (byte)(size);	//size2
			for (int i = 0; i < size; i++) OutData[add++] = inBuf[i];
			for (int i = 1; i < add; i++)
			{
				chksum += OutData[i];
				chksum %= 256;
			}
			OutData[add++] = (byte)(255 - chksum);
			if (cRS232.msc[inCH].IsOpen == false) return;
			cRS232.msc[inCH].Write(OutData, 0, add);
		}
		

		public static void RS232Command(int inCH, byte inCMD)
		{
			byte[] OutData = new byte[2048];
			int chksum = 0;
			int add = 0;
			OutData[add++] = 0x02;
			OutData[add++] = (byte)inCMD;
			OutData[add++] = 0;	//size1
			OutData[add++] = 0;	//size2
			for (int i = 1; i < add; i++)
			{
				chksum += OutData[i];
				chksum %= 256;
			}
			OutData[add++] = (byte)(255 - chksum);
			if (cRS232.msc[inCH].IsOpen == false) return;
			cRS232.msc[inCH].Write(OutData, 0, add);
		}

		public static void RS232Command(int inCH, byte inCMD, byte inVal)
		{

			if (cRS232.msc[inCH].IsOpen == false) return;

			byte[] OutData = new byte[8];
			int chksum = 0;
			int add = 0;
			OutData[add++] = 0x02;
			OutData[add++] = (byte)inCMD;
			OutData[add++] = 0x00;	//Size1
			OutData[add++] = 0x01;	//Size2
			OutData[add++] = inVal;
			for (int i = 1; i < add; i++)
			{
				chksum += OutData[i];
				chksum %= 256;
			}
			OutData[add++] = (byte)(255 - chksum);

			cRS232.msc[inCH].Write(OutData, 0, add);
		}
	}//end class
}
